package com.google.monkeyjump;

import java.io.IOException;
import java.util.Arrays;

import javax.microedition.khronos.opengles.GL10;

import org.anddev.andengine.audio.sound.Sound;
import org.anddev.andengine.audio.sound.SoundFactory;
import org.anddev.andengine.engine.Engine;
import org.anddev.andengine.engine.camera.Camera;
import org.anddev.andengine.engine.handler.IUpdateHandler;
import org.anddev.andengine.engine.handler.physics.PhysicsHandler;
import org.anddev.andengine.engine.handler.timer.ITimerCallback;
import org.anddev.andengine.engine.handler.timer.TimerHandler;
import org.anddev.andengine.engine.options.EngineOptions;
import org.anddev.andengine.engine.options.EngineOptions.ScreenOrientation;
import org.anddev.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
import org.anddev.andengine.entity.modifier.RotationModifier;
import org.anddev.andengine.entity.modifier.ScaleModifier;
import org.anddev.andengine.entity.primitive.Rectangle;
import org.anddev.andengine.entity.scene.CameraScene;
import org.anddev.andengine.entity.scene.Scene;
import org.anddev.andengine.entity.scene.Scene.IOnAreaTouchListener;
import org.anddev.andengine.entity.scene.Scene.IOnSceneTouchListener;
import org.anddev.andengine.entity.scene.Scene.ITouchArea;
import org.anddev.andengine.entity.scene.background.AutoParallaxBackground;
import org.anddev.andengine.entity.scene.background.ParallaxBackground.ParallaxEntity;
import org.anddev.andengine.entity.shape.Shape;
import org.anddev.andengine.entity.sprite.AnimatedSprite;
import org.anddev.andengine.entity.sprite.Sprite;
import org.anddev.andengine.entity.text.ChangeableText;
import org.anddev.andengine.entity.text.Text;
import org.anddev.andengine.entity.util.FPSLogger;
import org.anddev.andengine.extension.physics.box2d.PhysicsConnector;
import org.anddev.andengine.extension.physics.box2d.PhysicsFactory;
import org.anddev.andengine.extension.physics.box2d.PhysicsWorld;
import org.anddev.andengine.input.touch.TouchEvent;
import org.anddev.andengine.input.touch.detector.HoldDetector;
import org.anddev.andengine.opengl.font.Font;
import org.anddev.andengine.opengl.font.FontFactory;
import org.anddev.andengine.opengl.texture.TextureOptions;
import org.anddev.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlas;
import org.anddev.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
import org.anddev.andengine.opengl.texture.region.TextureRegion;
import org.anddev.andengine.opengl.texture.region.TiledTextureRegion;
import org.anddev.andengine.ui.activity.BaseGameActivity;
import org.anddev.andengine.util.Debug;
import org.anddev.andengine.util.HorizontalAlign;

import util.Background;
import util.Constants;

import android.content.Intent;
import android.graphics.Color;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;

import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.google.monkeyjump.db.DataBaseAdapter;
import com.google.monkeyjump.ranking.Rank;

/**
 *
 * 
 */
public class GameActivity extends BaseGameActivity implements
IOnAreaTouchListener, IOnSceneTouchListener {
	// ===========================================================
	// Constants
	// ===========================================================

	private static final int LIANA_ROTATION_DURATION = 30;
	private static final int CAMERA_WIDTH = 720;
	private static final int CAMERA_HEIGHT = 480;
	private static final float INITIAL_HUNTER_VELOCITY = 8f;
	private static final float DEFAULT_VELOCITY = 16;
	public static final float HUNTER_FINAL_POSITION = CAMERA_WIDTH / 2;


	// ===========================================================
	// Fields
	// ===========================================================

	private Camera mCamera;

	private BitmapTextureAtlas mBitmapTextureAtlas;
	private TiledTextureRegion mMonkeyTextureRegion;
	private TiledTextureRegion mHunterTextureRegion;
	private TiledTextureRegion mLianaTextureRegion;

	private BitmapTextureAtlas mAutoParallaxBackgroundTexture;

	private TextureRegion mParallaxLayerBack;
	private TextureRegion mParallaxLayerMid;
//	private TextureRegion mParallaxLayerFront;

	private AnimatedSprite monkey;
	private Scene scene;
	private AnimatedSprite hunter;
	private AnimatedSprite lianaSprite;
	private Shape liana;

	private ChangeableText scoreText;
	private Text gameOver;

	private HoldDetector hold;
	private RotationModifier rotationEntityModifier;

	protected Body monkeyBody;
	protected Body lianaSpriteBody;
	
	private Sound mGameOverSound;
	private Text mGameOverText;


	/* The categories. */
	public static final short CATEGORYBIT_WALL = 1;
	public static final short CATEGORYBIT_BOX = 2;
	public static final short CATEGORYBIT_MONKEY = 4;
	public static final short CATEGORYBIT_HUNTER = 8;

	/* And what should collide with what. */
	public static final short MASKBITS_WALL = CATEGORYBIT_WALL
			+ CATEGORYBIT_BOX + CATEGORYBIT_MONKEY + CATEGORYBIT_HUNTER;
	public static final short MASKBITS_BOX = CATEGORYBIT_WALL + CATEGORYBIT_BOX; // Missing:
	// CATEGORYBIT_CIRCLE
	public static final short MASKBITS_MONKEY = CATEGORYBIT_WALL
			+ CATEGORYBIT_MONKEY; // Missing: CATEGORYBIT_BOX
	public static final short MASKBITS_HUNTER = CATEGORYBIT_WALL
			+ CATEGORYBIT_HUNTER; // Missing: CATEGORYBIT_BOX

	public static final FixtureDef WALL_FIXTURE_DEF = PhysicsFactory
			.createFixtureDef(0, 0f, 0f, false, CATEGORYBIT_WALL,
					MASKBITS_WALL, (short) 0);
	public static final FixtureDef BOX_FIXTURE_DEF = PhysicsFactory
			.createFixtureDef(0, 0f, 0f, false, CATEGORYBIT_BOX, MASKBITS_BOX,
					(short) 0);
	public static final FixtureDef MONKEY_FIXTURE_DEF = PhysicsFactory
			.createFixtureDef(0, 0f, 0f, false, CATEGORYBIT_MONKEY,
					MASKBITS_MONKEY, (short) 0);
	public static final FixtureDef HUNTER_FIXTURE_DEF = PhysicsFactory
			.createFixtureDef(0, 0f, 0f, false, CATEGORYBIT_HUNTER,
					MASKBITS_HUNTER, (short) 0);
	private long monkeyJumpTimeElapsed;
	public float verticalSpeed = 16;
	public float gravity = 1;
	private int lianaHeight;
	private double monkeySpeed = 16;
	private float monkeyHorizontalSpeed;

//	ParallaxEntity parallaxEntitySun;

	ParallaxEntity parallaxEntityCloud;
	ParallaxEntity parallaxEntityForest;

	private AutoParallaxBackground autoParallaxBackground;
	private boolean initialized = false;
	private float hunterSpeed;
	private int currentLevel = 1;
	protected float distanceTravelled;
	private Font scoreFont;
	private Font gameOverFont;
	private BitmapTextureAtlas scoreFontTexture;
	private BitmapTextureAtlas gameOverFontTexture;
	public int score;
	private ChangeableText levelText;
	private ChangeableText distanceText;
	private float hunterDistance;
	private RotationModifier monkeyRotationEntityModifier;
	private boolean gameEnded = false;
	private boolean done = false;
	private CameraScene mPauseScene;
	private TextureRegion mPausedTextureRegion;
	private BitmapTextureAtlas pauseTextureAtlas;

	// ===========================================================
	// Constructors
	// ===========================================================

	// ===========================================================
	// Getter & Setter
	// ===========================================================

	// ===========================================================
	// Methods for/from SuperClass/Interfaces
	// ===========================================================

	@Override
	public Engine onLoadEngine() {
		this.mCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
		final EngineOptions engineOptions = new EngineOptions(true,
				ScreenOrientation.LANDSCAPE, new RatioResolutionPolicy(
						CAMERA_WIDTH, CAMERA_HEIGHT), this.mCamera);
		engineOptions.getTouchOptions().setRunOnUpdateThread(true);
		return new Engine(engineOptions);

	}
	
	@Override
	public void onPauseGame() {
		// TODO Auto-generated method stub
		super.onPauseGame();
	}

	@Override
	public void onLoadResources() {
		BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");
		this.pauseTextureAtlas = new BitmapTextureAtlas(256, 128, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
		this.mPausedTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.pauseTextureAtlas, this, "paused.png", 0, 0);
		

		FontFactory.setAssetBasePath("font/");
		this.scoreFontTexture = new BitmapTextureAtlas(512, 512, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
		this.scoreFont = FontFactory.createFromAsset(this.scoreFontTexture, this, "Plok.ttf", 20, true, Color.WHITE);

		this.mEngine.getTextureManager().loadTexture(this.scoreFontTexture);
		this.getFontManager().loadFont(this.scoreFont);
		
		this.mBitmapTextureAtlas = new BitmapTextureAtlas(2048, 128,
				TextureOptions.BILINEAR_PREMULTIPLYALPHA);
		this.mMonkeyTextureRegion = BitmapTextureAtlasTextureRegionFactory
				.createTiledFromAsset(this.mBitmapTextureAtlas, this,
						"jumping.png", 0, 0, 1, 2);
		this.mHunterTextureRegion = BitmapTextureAtlasTextureRegionFactory
				.createTiledFromAsset(this.mBitmapTextureAtlas, this,
						"hunter.png", 73, 0, 25, 1);
		this.mLianaTextureRegion = BitmapTextureAtlasTextureRegionFactory
				.createTiledFromAsset(this.mBitmapTextureAtlas, this,
						"macaco_no_cipo_reduzida.png", 0, 47, 1, 1);

		this.mAutoParallaxBackgroundTexture = new BitmapTextureAtlas(1024,
				1024, TextureOptions.DEFAULT);
//		this.mParallaxLayerFront = BitmapTextureAtlasTextureRegionFactory
//				.createFromAsset(this.mAutoParallaxBackgroundTexture, this,
//						"forest.png", 0, 0);
		this.mParallaxLayerBack = BitmapTextureAtlasTextureRegionFactory
				.createFromAsset(this.mAutoParallaxBackgroundTexture, this,
						"background.png", 0, 0);
		this.mParallaxLayerMid = BitmapTextureAtlasTextureRegionFactory
				.createFromAsset(this.mAutoParallaxBackgroundTexture, this,
						"parallax_background_layer_mid.png", 0, 500);

		this.mEngine.getTextureManager().loadTextures(this.mBitmapTextureAtlas,
				this.mAutoParallaxBackgroundTexture);

//		parallaxEntitySun = new ParallaxEntity(0.0f,
//				new Sprite(0, CAMERA_HEIGHT
//						- this.mParallaxLayerBack.getHeight(),
//						this.mParallaxLayerBack));

		parallaxEntityCloud = new ParallaxEntity(-5.0f,
				new Sprite(0, 80, this.mParallaxLayerMid));

		parallaxEntityForest = new ParallaxEntity(-10.0f,
				new Sprite(0, CAMERA_HEIGHT
						- this.mParallaxLayerBack.getHeight(),
						this.mParallaxLayerBack));
		
//		gameOverSound();
	}

	@Override
	public Scene onLoadScene() {
		this.mEngine.registerUpdateHandler(new FPSLogger());

		this.scene = new Scene();

		createPauseSprite();
		addBackGround();

		createWallFixtureDef();

		liana = createLiana();
		lianaHeight = (CAMERA_HEIGHT - this.mMonkeyTextureRegion.getTileHeight()) / 3;
		initMonkey(
				(CAMERA_WIDTH - this.mMonkeyTextureRegion.getTileWidth()) / 4,
				lianaHeight);

		initHunter();

		initMonkeyLiana();

		this.scoreText = new ChangeableText(5, 5, this.scoreFont, "Score: 0", "Score: XXXXXXXXXX".length());
		this.scoreText.setBlendFunction(GL10.GL_ONE, GL10.GL_ONE);
		this.scoreText.setAlpha(0);
		this.scene.attachChild(this.scoreText);
		
		this.distanceText = new ChangeableText(CAMERA_HEIGHT/2, 5, this.scoreFont, "Distance: 0 m", "Distance: XXXXXXXXXX m".length());
		this.distanceText.setBlendFunction(GL10.GL_ONE, GL10.GL_ONE);
		this.distanceText.setAlpha(0);
		this.scene.attachChild(this.distanceText);
		
		this.levelText = new ChangeableText(5, 30, this.scoreFont, "Level: 1", "Level: XXXXX".length());
		this.levelText.setBlendFunction(GL10.GL_ONE, GL10.GL_ONE);
		this.levelText.setAlpha(0);
		this.scene.attachChild(this.levelText);
		
		this.mGameOverText = new Text(0, 0, this.scoreFont, "Game\nOver", HorizontalAlign.CENTER);
		this.mGameOverText.setPosition((CAMERA_WIDTH - this.mGameOverText.getWidth()) * 0.5f, (CAMERA_HEIGHT - this.mGameOverText.getHeight()) * 0.5f);
		this.mGameOverText.registerEntityModifier(new ScaleModifier(3, 0.1f, 30.0f));
		this.mGameOverText.registerEntityModifier(new RotationModifier(3, 0, 720));
		
		// initJoints(scene);

		scene.attachChild(this.monkey);
		scene.attachChild(this.hunter);
		onHoldDetector();
		scene.registerUpdateHandler(hold);

		levelUpDetector();

		scene.setOnAreaTouchListener(this);
		scene.setOnSceneTouchListener(this);
		monkeyLianaCollisionDetector(this.monkey, (Rectangle) liana);
		
		gameOverDetector();

		return scene;
	}

	private void createPauseSprite() {
		this.mPauseScene = new CameraScene(this.mCamera);
		/* Make the 'PAUSED'-label centered on the camera. */
		final int x = CAMERA_WIDTH / 2 - this.mPausedTextureRegion.getWidth() / 2;
		final int y = CAMERA_HEIGHT / 2 - this.mPausedTextureRegion.getHeight() / 2;
		final Sprite pausedSprite = new Sprite(x, y, this.mPausedTextureRegion);
		this.mPauseScene.attachChild(pausedSprite);
		/* Makes the paused Game look through. */
		this.mPauseScene.setBackgroundEnabled(false);
	}

	@Override
	public boolean onSceneTouchEvent(Scene arg0, TouchEvent arg1) {
		if (gameEnded && done ){
			done = false;
			saveRank();
		}
		else {
			if(!initialized) {
				startGameConfig();
			}
			hold.onSceneTouchEvent(arg0, arg1);
		}
		return true;
	}

	/**
	 * Activate gravity and starts the hunter
	 */
	private void startGameConfig() {
		initialized = true;
		this.scene.registerUpdateHandler(new TimerHandler(0.2f, true,
				new HunterTimeAction()));
	}

	@Override
	public boolean onAreaTouched(TouchEvent arg0, ITouchArea arg1, float arg2,
			float arg3) {
		// TODO Auto-generated method stub
		return false;
	}

//	FIXME Fix what the game does when the "back" button is pressed
//	@Override
//	public boolean onKeyDown(int keyCode, KeyEvent event) {
//	    if ((keyCode == KeyEvent.KEYCODE_BACK)) {
//	    	return super.onKeyDown(KeyEvent.KEYCODE_HOME, event);
//	    }
//	    return false;
//	}
	
	@Override
	public void onLoadComplete() {

	}

	// ===========================================================
	// Methods
	// ===========================================================

	private void addBackGround() {
		mountBackGround();

		this.scene.setBackground(autoParallaxBackground);
	}

	private Shape createLiana() {
		final Shape liana = new Rectangle(
				(CAMERA_WIDTH - this.mMonkeyTextureRegion.getTileWidth()) / 4,
				(CAMERA_HEIGHT / 2), 15, 2);
		return liana;
	}

	private void createWallFixtureDef() {
		final Shape ground = new Rectangle(0, CAMERA_HEIGHT - 2, CAMERA_WIDTH,
				2);
		final Shape roof = new Rectangle(0, 0, CAMERA_WIDTH, 2);
		final Shape left = new Rectangle(0, 0, 2, CAMERA_HEIGHT);
		final Shape right = new Rectangle(CAMERA_WIDTH - 2, 0, 2, CAMERA_HEIGHT);

		scene.attachChild(ground);
		scene.attachChild(roof);
		scene.attachChild(left);
		scene.attachChild(right);

	}

	private void mountBackGround() {
		autoParallaxBackground = new AutoParallaxBackground(
				0, 0, 0, 5);

		autoParallaxBackground.attachParallaxEntity(parallaxEntityCloud);
		autoParallaxBackground.attachParallaxEntity(parallaxEntityForest);

	}

	private void levelUpDetector() {
		this.scene.registerUpdateHandler(new IUpdateHandler() {

			@Override
			public void reset() {
			}

			@Override
			public void onUpdate(final float pSecondsElapsed) {
				if (!gameEnded){
					if (currentLevel * 50 <= score) {
					currentLevel++;
					levelText.setText("Level: " + currentLevel);
				}
			}
		}});
	}

	private void monkeyLianaCollisionDetector(final AnimatedSprite sprite,
			final Rectangle liana) {
		this.scene.registerUpdateHandler(new IUpdateHandler() {

			
			@Override
			public void reset() {
			}

			@Override
			public void onUpdate(final float pSecondsElapsed) {
				if(!gameEnded){ 
					if (monkeyJumpTimeElapsed == 0) {
				
					monkeyJumpTimeElapsed = -1;

					// noGravityPhysicsWorld.destroyBody(monkeyBody);
					// monkey.setUserData(null);
					autoParallaxBackground.setParallaxChangePerSecond(3.5f);

					monkey.setPosition(monkey.getX(), liana.getY());

					monkey.setVisible(false);
					monkey.unregisterEntityModifier(monkeyRotationEntityModifier);
					rotationEntityModifier = new RotationModifier((float) (LIANA_ROTATION_DURATION/monkeySpeed), 380, 180);
					
					lianaSprite.registerEntityModifier(rotationEntityModifier);
					lianaSprite.setVisible(true);
					detectEndOfSwing();
				}
			}}
		});
	}

	private void initMonkey(float x, float y) {
		this.monkey = new AnimatedSprite(x, y, this.mMonkeyTextureRegion);
		this.monkey.setScaleCenterY(this.mMonkeyTextureRegion.getTileHeight());
		this.monkey.setScale(2);
		this.monkey.animate(new long[] { 200, 200, 200 }, 3, 5, true);

		final PhysicsHandler physicsHandler = new PhysicsHandler(this.monkey);
		this.monkey.registerUpdateHandler(physicsHandler);

	}

	/**
	 * 
	 */
	private void initMonkeyLiana() {

		this.lianaSprite = new AnimatedSprite(liana.getX(), liana.getY(),
				this.mLianaTextureRegion);
		this.lianaSprite.setVisible(false);
		this.lianaSprite.setScaleCenterY(this.mLianaTextureRegion
				.getTileHeight());
		this.lianaSprite.setScale(2);

		this.scene.attachChild(lianaSprite);
	}

	private void initHunter() {
		/*
		 * Calculate the coordinates for the face, so its centered on the
		 * camera.
		 */
		final int positionX = 10;
		final int positionY = CAMERA_HEIGHT
				- this.mHunterTextureRegion.getTileHeight() - 5;

		this.hunter = new AnimatedSprite(positionX, positionY,
				this.mHunterTextureRegion);
		hunter.setScaleCenterY(this.mHunterTextureRegion.getTileHeight());
		hunter.setScale(1);
		hunter.animate(generateTimeFrameArray(0, 25), 0, 25, true);
	}

	private long[] generateTimeFrameArray(int pFirstTitleIndex,
			int pLastTitleIndex) {
		long[] framesTime = new long[pLastTitleIndex - pFirstTitleIndex + 1];
		Arrays.fill(framesTime, 200);
		return framesTime;
	}

	private void monkeyJumpAction(float rotation) {
		scene.unregisterEntityModifier(rotationEntityModifier);
		rotationEntityModifier = null;
		
		monkey.setVisible(true);
		lianaSprite.setVisible(false);
		monkeyJumpTimeElapsed = 1;

		monkeyRotationEntityModifier = new RotationModifier((float) (1), rotation, 0);
		monkeyRotationEntityModifier.setRemoveWhenFinished(true);
		monkey.registerEntityModifier(monkeyRotationEntityModifier);
		
		//Velocity decomposition
		verticalSpeed = (float) Math.abs((monkeySpeed*Math.sin(Math.toRadians(lianaSprite.getRotation()) - Math.PI/2)));
		monkeyHorizontalSpeed = (float) Math.abs((monkeySpeed*Math.cos(Math.toRadians(lianaSprite.getRotation()) - Math.PI/2)));

		autoParallaxBackground.setParallaxChangePerSecond(monkeyHorizontalSpeed);

		TimerHandler monkeyTimeHandler = new TimerHandler(0.08f, true,
				new MonkeyTimeAction());
		this.scene.registerUpdateHandler(monkeyTimeHandler);

	}
	
	private final class MonkeyTimeAction implements ITimerCallback {

		@Override
		public void onTimePassed(final TimerHandler pTimerHandler) {
			if ((lianaHeight - monkey.getY() > - 60) || verticalSpeed > 0 ){
				monkey.setPosition(monkey.getX(), monkey.getY() - verticalSpeed);
				verticalSpeed -= gravity;
			}   else {
				scene.unregisterUpdateHandler(pTimerHandler);
				monkeySpeed = Math.min(Math.sqrt(Math.pow(verticalSpeed, 2) + Math.pow(monkeyHorizontalSpeed, 2)), 64);
				verticalSpeed = 0;
				monkeyJumpTimeElapsed = 0;
			}
			distanceTravelled += monkeyHorizontalSpeed;
			score = (int) distanceTravelled/250;
			scoreText.setText("Score: " + score);
			distanceText.setText("Distance: " + Float.valueOf(Math.max(0, hunterDistance)).longValue() + " m");
		}
	}

	// ===========================================================
	// Inner and Anonymous Classes
	// ===========================================================
	private final class HunterTimeAction implements ITimerCallback {

		@Override
		public void onTimePassed(final TimerHandler pTimerHandler) {
			if (!gameEnded) moveAction(GameActivity.this.hunter, GameActivity.INITIAL_HUNTER_VELOCITY);
		}
	}

	private void moveAction(final AnimatedSprite sprite, float deltaX) {
		hunterDistance = hunter.getX() * (-1);
		hunterSpeed = currentLevel * INITIAL_HUNTER_VELOCITY;
		hunter.setPosition(hunter.getX() + (hunterSpeed - monkeyHorizontalSpeed), 
				hunter.getY());


	}

	
	private void onHoldDetector() {
		hold = new HoldDetector(new HoldDetector.IHoldDetectorListener() {

			@Override	
			public void onHoldFinished(HoldDetector arg0, long arg1,
					float arg2, float arg3) {
				gravity = 1;
				if(lianaSprite.getRotation() > 180 && lianaSprite.getRotation() < 270) {
					monkeyJumpAction(lianaSprite.getRotation());
					lianaSprite.unregisterEntityModifier(rotationEntityModifier);
					rotationEntityModifier = null;
				}
			}

			@Override
			public void onHold(HoldDetector arg0, long arg1, float arg2,
					float arg3) {
				gravity = 3;

			}
		});
	}

	private void detectEndOfSwing() {
		scene.registerUpdateHandler(new IUpdateHandler() {
			@Override
			public void reset() {
				// TODO Auto-generated method stub

			}

			@Override
			public void onUpdate(float arg0) {
				if (!gameEnded ){
					if (rotationEntityModifier != null
						&& rotationEntityModifier.isFinished()) {
					lianaSprite.unregisterEntityModifier(rotationEntityModifier);
					rotationEntityModifier = null;
					scene.unregisterUpdateHandler(this);
					monkeySpeed = DEFAULT_VELOCITY;
					monkeyJumpAction(lianaSprite.getRotation());
				}
			}
			}});
	}
	
	private void gameOverDetector() {
		scene.registerUpdateHandler(new IUpdateHandler() {

			@Override
			public void reset() {
				// TODO Auto-generated method stub
			}

			@Override
			public void onUpdate(float arg0) {
				if (!gameEnded ){
					if(hunter.getX() >= HUNTER_FINAL_POSITION) {
						endGame();
					}
				}
			}

		});
	}

	private void endGame() {
		gameEnded = true;
		scene.detachChild(hunter);
		scene.detachChild(monkey);
		scene.detachChild(scoreText);
		scene.detachChild(distanceText);
		scene.detachChild(levelText);
		scene.detachChild(liana);
		scene.detachChild(lianaSprite);
		autoParallaxBackground.setParallaxChangePerSecond(0);
		
		TextureRegion mParallaxLayerGameOver = BitmapTextureAtlasTextureRegionFactory
				.createFromAsset(this.mAutoParallaxBackgroundTexture, this,
						"game_over_smaller.png", 0, 0);
		
		Sprite gameOverMonkey = new Sprite(80, 0, mParallaxLayerGameOver);
		autoParallaxBackground.detachParallaxEntity(parallaxEntityCloud);
		autoParallaxBackground.detachParallaxEntity(parallaxEntityForest);
		scene.attachChild(gameOverMonkey);
		
		this.gameOverFontTexture = new BitmapTextureAtlas(512, 512, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
		this.gameOverFont = FontFactory.createFromAsset(this.gameOverFontTexture, this, "Plok.ttf", 35, true, Color.WHITE);

		this.mEngine.getTextureManager().loadTexture(this.gameOverFontTexture);
		this.getFontManager().loadFont(this.gameOverFont);

		this.gameOver = new Text(CAMERA_WIDTH/2 - 140, CAMERA_HEIGHT - 45, this.gameOverFont, "Game Over");
		this.gameOver.setBlendFunction(GL10.GL_ONE, GL10.GL_ONE);
		this.gameOver.setAlpha(0);
		this.scene.attachChild(this.gameOver);
		
		done = true;	
		
	}
	
	protected void saveRank() {
		Intent saverank = new Intent(GameActivity.this, SaveRankActivity.class);
		saverank.putExtra(Constants.RANK_SAVE_ACTIVITY_SCORE_ID, score);
		this.finish();
		startActivity(saverank);
	}
	
	@Override
	public boolean onKeyDown(final int pKeyCode, final KeyEvent pEvent) {
		if(pKeyCode == KeyEvent.KEYCODE_MENU && pEvent.getAction() == KeyEvent.ACTION_DOWN) {
			if(this.mEngine.isRunning()) {
				this.scene.setChildScene(this.mPauseScene, false, true, true);
				this.mEngine.stop();
			} else {
				this.scene.clearChildScene();
				this.mEngine.start();
			}
			return true;
		} else {
			return super.onKeyDown(pKeyCode, pEvent);
		}
	}
	
}
